// **************************************************************
// COPYRIGHT(c)2020, Xidian University
// All rights reserved.
//
// IP LIB INDEX : 
// IP Name      : 
//                
// File name    :
// Module name  : 
// Full name    :
//
// Author       :  Hbing 
// Email        :  2629029232@qq.com
// Data         :  2020/8/27
// Version      :  V 1.0 
// 
//Abstract      :
// Called by    :  Father Module
// 
// Modification history
// ------------------------------------------------------------------------------------------------------
// 
//  
// *********************************************************************
`include "top_define.v"
// *******************
// TIMESCALE
// ******************* 
`timescale 1ns/1ps 

// *******************
// DESCRIPTION
// *******************
// V1.0 先按照严格优先级调度策略出队某个端口的数据帧--多播优先级最高--之后可以改进为加权优先级轮询
// 
// 
//*******************
//DEFINE(s)
//*******************
//`define UDLY 1    //Unit delay, for non-blocking assignments in sequential logic

//*******************
//DEFINE MODULE PORT
module schedule_dequeue(
	//sysrem input/output
	input  wire 		clk  ,
	input  wire 		rst_n,
	//with CPU_config
	output reg  [ 2:0]  query_CPU_node_min_threshold,
	input  wire [31:0]  CPU_node_min_threshold_data ,
	output reg 	[31:0]  ro_reg_np_dequeue_num		,
	output reg  [31:0]  ro_reg_np_max_tx_length     ,
	output reg 	[31:0]  tx_frame_cnt_node_0         ,
    output reg 	[31:0]  tx_frame_cnt_node_1         ,
    output reg 	[31:0]  tx_frame_cnt_node_2         ,
    output reg 	[31:0]  tx_frame_cnt_node_3         ,
    output reg 	[31:0]  tx_frame_cnt_node_4         ,
	//with schedule_enqueue
	input  wire 		queue_mem_init_done   ,   //队列链表信息RAM初始化完成
	(*mark_debug = "true"*) input  wire 		enqueue_executing_flag,
	(*mark_debug = "true"*) input  wire [ 5:0]  enqueue_number        ,
	(*mark_debug = "true"*) input  wire 		queue_head_update_done,
	(*mark_debug = "true"*) output reg  		dequeue_executing_flag,
	(*mark_debug = "true"*) output reg  [ 5:0]  dequeue_number_reg    ,

	input  wire [ 5:0]	enqueue_Linked_list_ram_wren ,
	input  wire [11:0]  enqueue_Linked_list_ram_waddr,
	input  wire [47:0]  enqueue_Linked_list_ram_wdata,
	//with queue_infor_management
	output reg  		dequeue_head_infor_wr_en  ,
	output reg  [  5:0] dequeue_head_infor_wr_addr,
	output reg  [ 31:0] dequeue_head_infor_wr_data,
	input  wire [ 31:0] dequeue_head_infor_rd_data,

	output reg  		dequeue_tail_infor_wr_en  ,
	output reg  [  5:0] dequeue_tail_infor_wr_addr,
	output reg  [ 15:0] dequeue_tail_infor_wr_data,
	// input  wire [ 15:0] dequeue_tail_infor_rd_data,

	output reg  		dequeue_length_infor_wr_en  ,
	output reg  [  5:0] dequeue_length_infor_wr_addr,
	output reg  [ 15:0] dequeue_length_infor_wr_data,
	input  wire [ 15:0] dequeue_length_infor_rd_data,

	input  wire         enqueue_length_infor_wr_en  ,
    input  wire [  5:0] enqueue_length_infor_wr_addr,
    input  wire [ 15:0] enqueue_length_infor_wr_data,

	output reg  		dequeue_node_length_wr_en  ,
	output reg  [  2:0] dequeue_node_length_wr_addr,
	output reg  [ 15:0] dequeue_node_length_wr_data,
	input  wire [ 15:0] dequeue_node_length_rd_data,

    input  wire         enqueue_node_length_wr_en  ,
    input  wire [  2:0] enqueue_node_length_wr_addr,
    input  wire [ 15:0] enqueue_node_length_wr_data,
	//with mem_management
	/*(*mark_debug = "true"*)*/ output reg  [ 11:0] dequeue_Linked_list_ram_raddr,
	/*(*mark_debug = "true"*)*/ input  wire [ 47:0] dequeue_Linked_list_ram_rdata,
	output reg  		dequeue_BD_public_used_update_en ,
	output reg  [ 31:0] dequeue_BD_public_used_update_num,
	//with mem_management_query
	// output reg  		memQuery            ,
	// output reg  [15:0]  memStartAddress     ,
	// output reg  [ 7:0]  mem_query_BD_num    ,
	// input  wire [15:0]  memQueryAddress     ,
	// input  wire [ 5:0]  lastBlockLength     ,
	// input  wire 		memQueryAddressValid,
	// input  wire 		memQueryAddressStart,
	// input  wire 		memQueryAddressEnd  ,
	// input  wire 		memQueryFrameLastBD ,

	// input  wire 		next_frame_infor_valid  ,
	// input  wire [15:0]	next_frame_first_BD_addr,
	// input  wire [10:0]  next_frame_length       ,
	// input  wire [15:0]  next_BD_addr            ,
	//with tx_fifo
		//多播
	/*(*mark_debug = "true"*)*/ input  wire 		tx_fifo_empty_mul,
	/*(*mark_debug = "true"*)*/ output reg  		tx_fifo_rden_mul ,
	/*(*mark_debug = "true"*)*/ input  wire [ 9:0]  tx_fifo_rdata_mul,  //4bit端口列表独热码+6bit队列号
		//单播
	/*(*mark_debug = "true"*)*/ input  wire 		tx_fifo_empty_7 ,
    /*(*mark_debug = "true"*)*/ output reg  		tx_fifo_rden_7  ,
    /*(*mark_debug = "true"*)*/ input  wire [ 5:0]  tx_fifo_rdata_7 ,  //队列号
    input  wire 		tx_fifo_empty_6 ,
    output reg  		tx_fifo_rden_6  ,
    input  wire [ 5:0]  tx_fifo_rdata_6 ,  //队列号
    input  wire 		tx_fifo_empty_5 ,
    output reg  		tx_fifo_rden_5  ,
    input  wire [ 5:0]  tx_fifo_rdata_5 ,  //队列号
    input  wire 		tx_fifo_empty_4 ,
    output reg  		tx_fifo_rden_4  ,
    input  wire [ 5:0]  tx_fifo_rdata_4 ,  //队列号
    input  wire 		tx_fifo_empty_3 ,
    output reg  		tx_fifo_rden_3  ,
    input  wire [ 5:0]  tx_fifo_rdata_3 ,  //队列号
    input  wire 		tx_fifo_empty_2 ,
    output reg  		tx_fifo_rden_2  ,
    input  wire [ 5:0]  tx_fifo_rdata_2 ,  //队列号
    input  wire 		tx_fifo_empty_1 ,
    output reg  		tx_fifo_rden_1  ,
    input  wire [ 5:0]  tx_fifo_rdata_1 ,  //队列号
    input  wire 		tx_fifo_empty_0 ,
    output reg  		tx_fifo_rden_0  ,
    input  wire [ 5:0]  tx_fifo_rdata_0 ,  //队列号
	//with sr_tx_fifo
		//多播
	/*(*mark_debug = "true"*)*/ input  wire 		sr_tx_fifo_full_mul ,  //将满标志--预留一个最长帧--深度-24
	/*(*mark_debug = "true"*)*/ output reg  		sr_tx_fifo_wren_mul ,
	/*(*mark_debug = "true"*)*/ output reg  [47:0]  sr_tx_fifo_wdata_mul,
	///*(*mark_debug = "true"*)*/ input  wire [ 7:0]  sr_tx_fifo_cnt_mul  ,
		//单播
	/*(*mark_debug = "true"*)*/ input  wire 		sr_tx_fifo_full_7 ,
    /*(*mark_debug = "true"*)*/ output reg  		sr_tx_fifo_wren_7 ,
    /*(*mark_debug = "true"*)*/ output reg  [47:0]  sr_tx_fifo_wdata_7,
    // (*mark_debug = "true"*) input  wire [ 7:0]  sr_tx_fifo_cnt_7  ,

     input  wire 		sr_tx_fifo_full_6 ,
     output reg  		sr_tx_fifo_wren_6 ,
     output reg  [47:0]  sr_tx_fifo_wdata_6,
     // input  wire [ 7:0]  sr_tx_fifo_cnt_6  ,

     input  wire 		sr_tx_fifo_full_5 ,
     output reg  		sr_tx_fifo_wren_5 ,
     output reg  [47:0]  sr_tx_fifo_wdata_5,
     // input  wire [ 7:0]  sr_tx_fifo_cnt_5  ,

     input  wire 		sr_tx_fifo_full_4 ,
     output reg  		sr_tx_fifo_wren_4 ,
     output reg  [47:0]  sr_tx_fifo_wdata_4,
     // input  wire [ 7:0]  sr_tx_fifo_cnt_4  ,

     input  wire 		sr_tx_fifo_full_3 ,
     output reg  		sr_tx_fifo_wren_3 ,
     output reg  [47:0]  sr_tx_fifo_wdata_3,
     // input  wire [ 7:0]  sr_tx_fifo_cnt_3  ,

     input  wire 		sr_tx_fifo_full_2 ,
     output reg  		sr_tx_fifo_wren_2 ,
     output reg  [47:0]  sr_tx_fifo_wdata_2,
     // input  wire [ 7:0]  sr_tx_fifo_cnt_2  ,

     input  wire 		sr_tx_fifo_full_1 ,
     output reg  		sr_tx_fifo_wren_1 ,
     output reg  [47:0]  sr_tx_fifo_wdata_1,
     // input  wire [ 7:0]  sr_tx_fifo_cnt_1  ,

     input  wire 		sr_tx_fifo_full_0 ,
     output reg  		sr_tx_fifo_wren_0 ,
     output reg  [47:0]  sr_tx_fifo_wdata_0
     // input  wire [ 7:0]  sr_tx_fifo_cnt_0  
	); 

//*******************
//DEFINE PARAMETER
//*******************
//Parameter(s) 
localparam IDLE              = 12'b0000_0000_0000;
localparam READ_TX_MUL       = 12'b0000_0000_0001;
localparam READ_TXFIFO_7     = 12'b0000_0000_0010;
localparam READ_TXFIFO_6     = 12'b0000_0000_0100;
localparam READ_TXFIFO_5     = 12'b0000_0000_1000;
localparam READ_TXFIFO_4     = 12'b0000_0001_0000;
localparam READ_TXFIFO_3     = 12'b0000_0010_0000;
localparam READ_TXFIFO_2     = 12'b0000_0100_0000;
localparam READ_TXFIFO_1     = 12'b0000_1000_0000;
localparam READ_TXFIFO_0     = 12'b0001_0000_0000;
localparam READ_QUEUE_INFOR  = 12'b0010_0000_0000;
localparam WR_DEQUEUE_RESULT = 12'b0100_0000_0000;
localparam DEQUEUE_FINISH    = 12'b1000_0000_0000;
//sr_tx_fifo
// _ _ _ 6 _ _  _ _ _ _4 _ _ _ _ _ _ _ _6_ _ _ _  _ _ _ _13 _ _ _ _ _ _11 _ _ _ _ _ _ 6 _ _ _ _ _ _ 1 _ _ _ _ _ 1 _ _
//|    47~42   |     41~38    |       37~32      |     31~19    |    18~ 8     |     7~2      |     1     |     0    |
//|___reserve__|_outport_list_|__dequeue_number__|__BD_address__|_frame_length_|_valid_length_|__first_BD_|__last_BD_|
//
//Linked_list_ram--字节写入，扩充为8的整数倍
// _ _ _1_ _ _ _ _ _1_ _ _ _ _ _ _ 7 _ _ _  _ _ _ 12 _ _ _ _ _ _ 11 _ _ _
//|    40     |    39     |      38~32     |     31~16    |     15~0     |
//|__first_BD_|__last_BD__|__valid_length__|__BD_address__|_frame_length_|
//*********************
//INNER SIGNAL DECLARATION
//*********************
//REGS
//状态机
(*mark_debug = "true"*) reg [11:0] c_state,n_state;
//出队节点号
(*mark_debug = "true"*) reg [2:0] dequeue_NodeID_c;
(*mark_debug = "true"*) reg [2:0] dequeue_NodeID;
(*mark_debug = "true"*) reg [2:0] dequeue_NodeID_reg;
//出队优先级
(*mark_debug = "true"*) reg [2:0] dequeue_pri_c;
(*mark_debug = "true"*) reg [2:0] dequeue_pri;
(*mark_debug = "true"*) reg [2:0] dequeue_pri_reg;
//出队号
(*mark_debug = "true"*) reg [5:0] dequeue_number;
reg [5:0] dequeue_number_reg_dl;
reg [5:0] enqueue_number_dl;
//单、多播标识
reg mul_flag;
reg mul_flag_reg;
//寄存多播目的端口列表
(*mark_debug = "true"*) reg [3:0] mul_outport;
//将输出端口转换为独热码
(*mark_debug = "true"*) reg [3:0] outport_list;
reg [3:0] outport_list_reg;
//入队更新链表与出队查询链表冲突处理信号
(*mark_debug = "true"*) reg [47:0] linked_list_rdata;  //查询BD链表的信息全部用此信号来得到
reg [ 5:0] enqueue_Linked_list_ram_wren_r;
reg [11:0] enqueue_Linked_list_ram_waddr_r;
reg [47:0] enqueue_Linked_list_ram_wdata_r;
reg [ 5:0] enqueue_Linked_list_ram_wren_r2;
reg [11:0] enqueue_Linked_list_ram_waddr_r2;
reg [47:0] enqueue_Linked_list_ram_wdata_r2;
//出队链表ram地址打一拍
reg [11:0] dequeue_Linked_list_ram_raddr_r;
reg [11:0] dequeue_Linked_list_ram_raddr_r2;
//队头防冲突
// reg 	   dequeue_infor_update_dl;
reg        enqueue_length_infor_wr_en_dl  ;
reg [ 5:0] enqueue_length_infor_wr_addr_dl;
reg [15:0] enqueue_length_infor_wr_data_dl;
reg        enqueue_node_length_wr_en_dl   ;
reg [ 5:0] enqueue_node_length_wr_addr_dl ;
reg [15:0] enqueue_node_length_wr_data_dl ;
//查询BD计数--1，2循环
(*mark_debug = "true"*) reg 	  wr_dequeue_working ;
(*mark_debug = "true"*) reg [3:0] wr_result_step;
//寄存帧长
reg [10:0] frame_length;
//根据帧长计算出队BD数
reg [ 3:0] dequeue_BD_num;
//队列信息更新冲突信号
reg queue_head_update_done_r;
reg queue_head_update_ever;
//写中间BD的信号
(*mark_debug = "true"*) reg mid_valid;
//写当前BD
(*mark_debug = "true"*) reg [12:0] sr_BD_addr;
(*mark_debug = "true"*) reg [12:0] head_BD_addr;
//tx_fifo采样
reg [ 9:0] tx_fifo_rdata_mul_reg;
reg [ 5:0] tx_fifo_rdata_7_reg	;
reg [ 5:0] tx_fifo_rdata_6_reg	;
reg [ 5:0] tx_fifo_rdata_5_reg	;
reg [ 5:0] tx_fifo_rdata_4_reg	;
reg [ 5:0] tx_fifo_rdata_3_reg	;
reg [ 5:0] tx_fifo_rdata_2_reg	;
reg [ 5:0] tx_fifo_rdata_1_reg	;
reg [ 5:0] tx_fifo_rdata_0_reg	;
reg        tx_fifo_empty_mul_reg;	
reg        tx_fifo_empty_7_reg  ;
reg        tx_fifo_empty_6_reg  ;
reg        tx_fifo_empty_5_reg  ;
reg        tx_fifo_empty_4_reg  ;
reg        tx_fifo_empty_3_reg  ;
reg        tx_fifo_empty_2_reg  ;
reg        tx_fifo_empty_1_reg  ;
reg        tx_fifo_empty_0_reg  ;
//链表ram采样
reg  [47:0] dequeue_Linked_list_ram_rdata_reg;

//max_frame_lenth_cnt
reg  [19:0] time_1ms_cnt;
reg  [31:0] frame_length_cnt;
//WIRES
wire [ 5:0] dequeue_number_c; 
//当前拍队首BD地址以及出队帧长
wire [12:0] head_BD_addr_c;
wire [10:0] frame_length_c;

(*mark_debug = "true"*) wire 		last_step_of_last_BD;

(*mark_debug = "true"*) wire [15:0] length_infor_rd_data;
(*mark_debug = "true"*) wire [15:0] node_length_rd_data;
//*********************
//INSTANTCE MODULE
//*********************

//******************* ram采样 *****************
//tx_fifo采样
always @(posedge clk or negedge rst_n) begin
	if(~rst_n) begin
		tx_fifo_rdata_mul_reg	<= 10'b0 			;
		tx_fifo_rdata_7_reg		<= 6'b0 			;
		tx_fifo_rdata_6_reg		<= 6'b0 			;
		tx_fifo_rdata_5_reg		<= 6'b0 			;
		tx_fifo_rdata_4_reg		<= 6'b0 			;
		tx_fifo_rdata_3_reg		<= 6'b0 			;
		tx_fifo_rdata_2_reg		<= 6'b0 			;
		tx_fifo_rdata_1_reg		<= 6'b0 			;
		tx_fifo_rdata_0_reg		<= 6'b0 			;
		tx_fifo_empty_mul_reg	<= 1'b1 			;
		tx_fifo_empty_7_reg		<= 1'b1 			; 
		tx_fifo_empty_6_reg		<= 1'b1 			; 
		tx_fifo_empty_5_reg		<= 1'b1 			; 
		tx_fifo_empty_4_reg		<= 1'b1 			; 
		tx_fifo_empty_3_reg		<= 1'b1 			; 
		tx_fifo_empty_2_reg		<= 1'b1 			; 
		tx_fifo_empty_1_reg		<= 1'b1 			; 
		tx_fifo_empty_0_reg		<= 1'b1 			; 	
	end
	else begin
		tx_fifo_rdata_mul_reg	<= tx_fifo_rdata_mul;
		tx_fifo_rdata_7_reg		<= tx_fifo_rdata_7  ;
		tx_fifo_rdata_6_reg		<= tx_fifo_rdata_6  ;
		tx_fifo_rdata_5_reg		<= tx_fifo_rdata_5  ;
		tx_fifo_rdata_4_reg		<= tx_fifo_rdata_4  ;
		tx_fifo_rdata_3_reg		<= tx_fifo_rdata_3  ;
		tx_fifo_rdata_2_reg		<= tx_fifo_rdata_2  ;
		tx_fifo_rdata_1_reg		<= tx_fifo_rdata_1  ;
		tx_fifo_rdata_0_reg		<= tx_fifo_rdata_0  ;
		tx_fifo_empty_mul_reg	<= tx_fifo_empty_mul;
		tx_fifo_empty_7_reg		<= tx_fifo_empty_7  ; 
		tx_fifo_empty_6_reg		<= tx_fifo_empty_6  ; 
		tx_fifo_empty_5_reg		<= tx_fifo_empty_5  ; 
		tx_fifo_empty_4_reg		<= tx_fifo_empty_4  ; 
		tx_fifo_empty_3_reg		<= tx_fifo_empty_3  ; 
		tx_fifo_empty_2_reg		<= tx_fifo_empty_2  ; 
		tx_fifo_empty_1_reg		<= tx_fifo_empty_1  ; 
		tx_fifo_empty_0_reg		<= tx_fifo_empty_0  ; 
	end
end
//链表ram采样
always @(posedge clk or negedge rst_n) begin
	if(~rst_n) begin
		dequeue_Linked_list_ram_rdata_reg <= 48'b0;
	end
	else begin
		dequeue_Linked_list_ram_rdata_reg <= dequeue_Linked_list_ram_rdata;
	end	
end

//****************队长防冲突*****************
always @(posedge clk or negedge rst_n) begin
	if(~rst_n) begin
		enqueue_length_infor_wr_en_dl   <= 1'b0     ;
		enqueue_length_infor_wr_addr_dl <= 6'b0 	;
		enqueue_length_infor_wr_data_dl <= 16'b0 	;
		enqueue_node_length_wr_en_dl    <= 1'b0     ;
		enqueue_node_length_wr_addr_dl  <= 6'b0 	;
		enqueue_node_length_wr_data_dl  <= 16'b0 	;		
	end
	else begin
		enqueue_length_infor_wr_en_dl   <= enqueue_length_infor_wr_en  ;
		enqueue_length_infor_wr_addr_dl <= enqueue_length_infor_wr_addr;
		enqueue_length_infor_wr_data_dl <= enqueue_length_infor_wr_data;
		enqueue_node_length_wr_en_dl    <= enqueue_node_length_wr_en   ;
		enqueue_node_length_wr_addr_dl  <= enqueue_node_length_wr_addr ;
		enqueue_node_length_wr_data_dl  <= enqueue_node_length_wr_data ;	
	end
end

assign length_infor_rd_data = (((enqueue_length_infor_wr_en) && (enqueue_length_infor_wr_addr == dequeue_number_reg))? (enqueue_length_infor_wr_data) : 
                            (((enqueue_length_infor_wr_en_dl) && (enqueue_length_infor_wr_addr_dl == dequeue_number_reg))? (enqueue_length_infor_wr_data_dl) :
                            (dequeue_length_infor_rd_data)));
assign node_length_rd_data =(((enqueue_node_length_wr_en) && (enqueue_node_length_wr_addr == dequeue_NodeID_reg))? (enqueue_node_length_wr_data) : 
                            (((enqueue_node_length_wr_en_dl) && (enqueue_node_length_wr_addr_dl == {3'b0,dequeue_NodeID_reg}))? (enqueue_node_length_wr_data_dl) :
                            (dequeue_node_length_rd_data)));

//*********************
//MAIN CORE
//*********************

//三段式状态机
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		c_state <= IDLE;
	end
	else begin
		c_state <= n_state;
	end
end

always @(*) begin
	case(c_state)
		IDLE:
		begin  //预留一个以太网最长帧
			if (queue_mem_init_done == 1'b1) begin  //tx_fifo均为首字置出，数据先用，后拉高读使能
				if ((sr_tx_fifo_full_mul == 1'b0) /*&& (sr_tx_fifo_cnt_mul <= 'd103)*/ && (tx_fifo_empty_mul_reg == 1'b0)) begin
					n_state = READ_TX_MUL;
				end
				else if ((sr_tx_fifo_full_7 == 1'b0) /*&& (sr_tx_fifo_cnt_7 <= 'd103)*/ && (tx_fifo_empty_7_reg == 1'b0)) begin
					n_state = READ_TXFIFO_7;
				end
				else if ((sr_tx_fifo_full_6 == 1'b0) /*&& (sr_tx_fifo_cnt_6 <= 'd103)*/ && (tx_fifo_empty_6_reg == 1'b0)) begin
					n_state = READ_TXFIFO_6;
				end
				else if ((sr_tx_fifo_full_5 == 1'b0) /*&& (sr_tx_fifo_cnt_5 <= 'd103)*/ && (tx_fifo_empty_5_reg == 1'b0)) begin
					n_state = READ_TXFIFO_5;
				end
				else if ((sr_tx_fifo_full_4 == 1'b0) /*&& (sr_tx_fifo_cnt_4 <= 'd103)*/ && (tx_fifo_empty_4_reg == 1'b0)) begin
					n_state = READ_TXFIFO_4;
				end
				else if ((sr_tx_fifo_full_3 == 1'b0) /*&& (sr_tx_fifo_cnt_3 <= 'd103)*/ && (tx_fifo_empty_3_reg == 1'b0)) begin
					n_state = READ_TXFIFO_3;
				end
				else if ((sr_tx_fifo_full_2 == 1'b0) /*&& (sr_tx_fifo_cnt_2 <= 'd103)*/ && (tx_fifo_empty_2_reg == 1'b0)) begin
					n_state = READ_TXFIFO_2;
				end
				else if ((sr_tx_fifo_full_1 == 1'b0) /*&& (sr_tx_fifo_cnt_1 <= 'd103)*/ && (tx_fifo_empty_1_reg == 1'b0)) begin
					n_state = READ_TXFIFO_1;
				end
				else if ((sr_tx_fifo_full_0 == 1'b0) /*&& (sr_tx_fifo_cnt_0 <= 'd103)*/ && (tx_fifo_empty_0_reg == 1'b0)) begin
					n_state = READ_TXFIFO_0;
				end
				else begin
					n_state = IDLE;
				end
			end
			else begin
				n_state = IDLE;
			end
		end
		READ_TX_MUL:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_7:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_6:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_5:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_4:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_3:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_2:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_1:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_TXFIFO_0:
		begin
			n_state = READ_QUEUE_INFOR;
		end
		READ_QUEUE_INFOR:
		begin
			// n_state = WR_DEQUEUE_RESULT;
			// 转移状态--条件当搬移到上一个BD块最后一拍时
			if(wr_dequeue_working) begin
				n_state = READ_QUEUE_INFOR;
			end
			else begin
				n_state = WR_DEQUEUE_RESULT;
			end
		end
		WR_DEQUEUE_RESULT:
		begin
			n_state = IDLE;
		end
		default:
		begin
			n_state = IDLE;
		end
	endcase
end

//出队正在执行标志
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_executing_flag <= 1'b0;
	end
	else if ((n_state == WR_DEQUEUE_RESULT)) begin
		dequeue_executing_flag <= 1'b1;
	end
	else if ((wr_dequeue_working) && (last_step_of_last_BD)) begin
		dequeue_executing_flag <= 1'b0;
	end
	else begin
		dequeue_executing_flag <= dequeue_executing_flag;
	end
end

//tx_fifo采样
// always @(posedge clk) begin
// 	tx_fifo_rdata_mul_reg	<= tx_fifo_rdata_mul;
// 	tx_fifo_rdata_7_reg		<= tx_fifo_rdata_7  ;
// 	tx_fifo_rdata_6_reg		<= tx_fifo_rdata_6  ;
// 	tx_fifo_rdata_5_reg		<= tx_fifo_rdata_5  ;
// 	tx_fifo_rdata_4_reg		<= tx_fifo_rdata_4  ;
// 	tx_fifo_rdata_3_reg		<= tx_fifo_rdata_3  ;
// 	tx_fifo_rdata_2_reg		<= tx_fifo_rdata_2  ;
// 	tx_fifo_rdata_1_reg		<= tx_fifo_rdata_1  ;
// 	tx_fifo_rdata_0_reg		<= tx_fifo_rdata_0  ;	
// end
//寄存出队节点号以及优先级--当前拍
always @(*) begin
	case(n_state)
		READ_TX_MUL:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_mul_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_mul_reg[2:0];
		end
		READ_TXFIFO_7:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_7_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_7_reg[2:0];
		end
		READ_TXFIFO_6:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_6_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_6_reg[2:0];
		end
		READ_TXFIFO_5:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_5_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_5_reg[2:0];
		end
		READ_TXFIFO_4:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_4_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_4_reg[2:0];
		end
		READ_TXFIFO_3:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_3_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_3_reg[2:0];
		end
		READ_TXFIFO_2:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_2_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_2_reg[2:0];
		end
		READ_TXFIFO_1:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_1_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_1_reg[2:0];
		end
		READ_TXFIFO_0:
		begin
			dequeue_NodeID_c = tx_fifo_rdata_0_reg[5:3];
			dequeue_pri_c    = tx_fifo_rdata_0_reg[2:0];
		end
		default:
		begin
			dequeue_NodeID_c = 3'd0;
			dequeue_pri_c    = 3'd0;
		end
	endcase
end
assign dequeue_number_c = {dequeue_NodeID_c,dequeue_pri_c};

//产生单多播标识
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		mul_flag <= 1'b0;
	end
	else if ((c_state == IDLE) && (n_state == READ_TX_MUL)) begin
		mul_flag <= 1'b1;
	end
	else if ((c_state == IDLE) && (n_state != READ_TX_MUL)) begin
		mul_flag <= 1'b0;
	end
	// else if (c_state == DEQUEUE_FINISH) begin
	// 	mul_flag <= 1'b0;
	// end
	else begin
		mul_flag <= mul_flag;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		mul_flag_reg <= 1'b0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin
		mul_flag_reg <= mul_flag;
	end
	else begin
		mul_flag_reg <= mul_flag_reg;
	end
end

// //寄存入队写BD链表RAM信号，避免查询冲突
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		enqueue_Linked_list_ram_wren_r  <= 6'd0;
		enqueue_Linked_list_ram_waddr_r <= 12'd0;
		enqueue_Linked_list_ram_wdata_r <= 48'b0;
		enqueue_Linked_list_ram_wren_r2  <= 6'd0;
		enqueue_Linked_list_ram_waddr_r2 <= 12'd0;
		enqueue_Linked_list_ram_wdata_r2 <= 48'b0;
	end
	else begin
		enqueue_Linked_list_ram_wren_r  <= enqueue_Linked_list_ram_wren;
		enqueue_Linked_list_ram_waddr_r <= enqueue_Linked_list_ram_waddr;
		enqueue_Linked_list_ram_wdata_r <= enqueue_Linked_list_ram_wdata;
		enqueue_Linked_list_ram_wren_r2  <= enqueue_Linked_list_ram_wren_r;
		enqueue_Linked_list_ram_waddr_r2 <= enqueue_Linked_list_ram_waddr_r;
		enqueue_Linked_list_ram_wdata_r2 <= enqueue_Linked_list_ram_wdata_r;
	end
end

//BD链表RAM读数据--读地址只有在读当前帧尾BD的下一跳时可能会与入队将下一帧首BD链到当前帧尾BD下一跳发生冲突，所以进行冲突避免
always @(*) begin
	if ((enqueue_Linked_list_ram_wren == 6'b001111) && (enqueue_Linked_list_ram_waddr == dequeue_Linked_list_ram_raddr_r2)) begin
		linked_list_rdata = {dequeue_Linked_list_ram_rdata_reg[47:32],enqueue_Linked_list_ram_wdata[31:0]};
	end
	else if ((enqueue_Linked_list_ram_wren_r == 6'b001111) && (enqueue_Linked_list_ram_waddr_r == dequeue_Linked_list_ram_raddr_r2)) begin
		linked_list_rdata = {dequeue_Linked_list_ram_rdata_reg[47:32],enqueue_Linked_list_ram_wdata_r[31:0]};
	end
	else if ((enqueue_Linked_list_ram_wren_r2 == 6'b001111) && (enqueue_Linked_list_ram_waddr_r2 == dequeue_Linked_list_ram_raddr_r2)) begin
		linked_list_rdata = {dequeue_Linked_list_ram_rdata_reg[47:32],enqueue_Linked_list_ram_wdata_r2[31:0]};
	end
	else begin
		linked_list_rdata = dequeue_Linked_list_ram_rdata_reg;
	end
end

//在n_state寄存
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_NodeID <= 3'd0;
		dequeue_pri    <= 3'd0;
	end
	else if ((c_state == IDLE) && (n_state != IDLE)) begin
		dequeue_NodeID <= dequeue_NodeID_c ;
		dequeue_pri    <= dequeue_pri_c    ;
	end
	else begin
		dequeue_NodeID <= dequeue_NodeID;
		dequeue_pri    <= dequeue_pri   ;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_NodeID_reg <= 3'd0;
		dequeue_pri_reg    <= 3'd0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin
		dequeue_NodeID_reg <= dequeue_NodeID ;
		dequeue_pri_reg    <= dequeue_pri    ;
	end
	else begin
		dequeue_NodeID_reg <= dequeue_NodeID_reg;
		dequeue_pri_reg    <= dequeue_pri_reg   ;
	end
end

//出队队列号
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_number <= 6'd0;
	end
	else if ((c_state == IDLE) && (n_state != IDLE)) begin
		dequeue_number <= dequeue_number_c;
	end
	else begin
		dequeue_number <= dequeue_number;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_number_reg <= 6'd0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin
		dequeue_number_reg <= dequeue_number;
	end
	else begin
		dequeue_number_reg <= dequeue_number_reg;
	end
end

//寄存多播目的端口列表
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		mul_outport <= 4'd0;
	end
	else if (n_state == READ_TX_MUL) begin
		mul_outport <= tx_fifo_rdata_mul_reg[9:6];
	end
	else if (n_state == DEQUEUE_FINISH) begin
		mul_outport <= 4'd0;
	end
	else begin
		mul_outport <= mul_outport;
	end
end

//输出端口独热码
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		outport_list <= 4'd0;
	end
	else if ((c_state == READ_TX_MUL) && (n_state == READ_QUEUE_INFOR)) begin
		outport_list <= mul_outport;
	end
	else if ((n_state == READ_QUEUE_INFOR) && (c_state != READ_QUEUE_INFOR)) begin
		case(dequeue_NodeID)
			3'd3   :outport_list <= 4'b1000;
			3'd2   :outport_list <= 4'b0100;
			3'd1   :outport_list <= 4'b0010;
			3'd0   :outport_list <= 4'b0001;
			default:outport_list <= 4'b0000;
		endcase
	end
	else begin
		outport_list <= outport_list;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		outport_list_reg <= 4'd0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin
		outport_list_reg <= outport_list;
	end
	else begin
		outport_list_reg <= outport_list_reg;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		wr_dequeue_working <= 1'd0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin
		wr_dequeue_working <= 1'b1;
	end
	else if (last_step_of_last_BD) begin
		wr_dequeue_working <= 1'b0;
	end
	else begin
		wr_dequeue_working <= wr_dequeue_working;
	end
end

//查询BD链表打拍
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		wr_result_step <= 3'd0;
	end
	else if ((n_state == WR_DEQUEUE_RESULT) || wr_dequeue_working) begin
		if (last_step_of_last_BD) begin
			wr_result_step <= 3'b0;
		end
		else if (wr_result_step == 3'd4) begin
			wr_result_step <= 3'd1;
		end
		else if (wr_result_step == 3'd3 && (~linked_list_rdata[39])) begin
			wr_result_step <= 3'd1;
		end
		else begin
			wr_result_step <= wr_result_step + 3'd1;
		end
	end
	else begin
		wr_result_step <= 3'd0;
	end
end

//在READ_QUEUE_INFO状态下得到队首信息
assign head_BD_addr_c = dequeue_head_infor_rd_data[28:16];
assign frame_length_c = dequeue_head_infor_rd_data[10:0];

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		frame_length <= 11'd0;
		head_BD_addr <= 13'd0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin
		frame_length <= frame_length_c;
		head_BD_addr <= head_BD_addr_c;
	end
	// else if (c_state == DEQUEUE_FINISH) begin
	// 	frame_length <= 11'd0;
	// 	head_BD_addr <= 13'd0;
	// end
	else begin
		frame_length <= frame_length;
		head_BD_addr <= head_BD_addr;
	end
end

//根据出队帧长计算出队BD数量
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_BD_num <= 4'd0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin
		if (frame_length_c[6:0] == 7'd0) begin
			dequeue_BD_num <= frame_length_c[10:7];
		end
		else begin
			dequeue_BD_num <= frame_length_c[10:7] + 4'd1;
		end
	end
	else begin
		dequeue_BD_num <= dequeue_BD_num;
	end
end

//给出BD链表读地址
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_Linked_list_ram_raddr <= 12'd0;
	end
	else if (n_state == WR_DEQUEUE_RESULT) begin  //第一拍，给出当前队首的首BD地址
		dequeue_Linked_list_ram_raddr <= head_BD_addr_c[11:0];
	end
	else if ((wr_dequeue_working) && (wr_result_step == 3'd3)) begin  //1得到读地址，2得到读数据
		dequeue_Linked_list_ram_raddr <= linked_list_rdata[27:16];
	end
	else begin
		dequeue_Linked_list_ram_raddr <= dequeue_Linked_list_ram_raddr;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_Linked_list_ram_raddr_r 	<= 12'd0;
		dequeue_Linked_list_ram_raddr_r2 	<= 12'd0;
	end
	else begin
		dequeue_Linked_list_ram_raddr_r 	<= dequeue_Linked_list_ram_raddr 	;
		dequeue_Linked_list_ram_raddr_r2 	<= dequeue_Linked_list_ram_raddr_r 	;
	end
end 

//寄存入队已经更新队首信号
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		queue_head_update_done_r <= 1'b0;
	end
	else begin
		queue_head_update_done_r <= queue_head_update_done;
	end
end

//入队更新了队首
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		queue_head_update_ever <= 1'b0;
	end
	else if (dequeue_executing_flag == 1'b1) begin
		if ((queue_head_update_done == 1'b1) && (queue_head_update_done_r == 1'b0) && (enqueue_executing_flag == 1'b1) && (enqueue_number == dequeue_number)) begin
			queue_head_update_ever <= 1'b1;
		end
		else begin
			queue_head_update_ever <= queue_head_update_ever;
		end
	end
	else begin
		queue_head_update_ever <= 1'b0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_number_reg_dl <= 6'b0;
		enqueue_number_dl     <= 6'b0;
	end
	else if (last_step_of_last_BD) begin
		dequeue_number_reg_dl <= dequeue_number_reg;
		enqueue_number_dl 	  <= enqueue_number;
	end
	else begin
		dequeue_number_reg_dl <= dequeue_number_reg_dl;
		enqueue_number_dl 	  <= enqueue_number_dl;
	end
end


//更新队列信息
	//队首
assign last_step_of_last_BD = wr_dequeue_working && (wr_result_step == 3'd4) && linked_list_rdata[39];
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_head_infor_wr_en   <= 1'b0;
		dequeue_head_infor_wr_addr <= 6'd0;
		dequeue_head_infor_wr_data <= 32'd0;
		// dequeue_infor_update_dl    <= 1'b0;
	end
	// else if ((c_state == IDLE) && (n_state != IDLE)) begin
	// 	dequeue_head_infor_wr_en   <= 1'b0;
	// 	dequeue_head_infor_wr_addr <= dequeue_number_c;
	// 	dequeue_head_infor_wr_data <= 32'd0;
	// end
	else if(linked_list_rdata[39] && (wr_result_step == 3'd3)) begin
	 	if (linked_list_rdata[10:0] == 11'd0) begin  //下一帧长为0，队列只有一帧
			if (((enqueue_number == dequeue_number_reg) && (queue_head_update_done)) || (queue_head_update_ever)) begin  //入队出队更新同一队列，入队更新队首完毕
				dequeue_head_infor_wr_en   <= 1'b0;
				dequeue_head_infor_wr_addr <= dequeue_head_infor_wr_addr;
				dequeue_head_infor_wr_data <= linked_list_rdata[31:0];
				// dequeue_infor_update_dl    <= 1'b0;
			end
			else begin  //入队出队没有更新同一队列，队首出完，写0
				dequeue_head_infor_wr_en   <= 1'b1;
				dequeue_head_infor_wr_addr <= dequeue_number_reg;
				dequeue_head_infor_wr_data <= 32'd0;
				// dequeue_infor_update_dl    <= 1'b0;
			end
		end
		else begin  //有下一帧，更新为当前队首
			dequeue_head_infor_wr_en   <= 1'b1;
			dequeue_head_infor_wr_addr <= dequeue_number_reg;
			dequeue_head_infor_wr_data <= linked_list_rdata[31:0];
			// dequeue_infor_update_dl    <= 1'b0;
		end
	end
	// else if(dequeue_infor_update_dl) begin
	//  	if (linked_list_rdata[10:0] == 11'd0) begin  //下一帧长为0，队列只有一帧
	// 		if (((enqueue_number_dl == dequeue_number_reg_dl) && (queue_head_update_done)) || (queue_head_update_ever)) begin  //入队出队更新同一队列，入队更新队首完毕
	// 			dequeue_head_infor_wr_en   <= 1'b0;
	// 			dequeue_head_infor_wr_addr <= dequeue_head_infor_wr_addr;
	// 			dequeue_head_infor_wr_data <= linked_list_rdata[31:0];
	// 			dequeue_infor_update_dl    <= 1'b0;
	// 		end
	// 		else begin  //入队出队没有更新同一队列，队首出完，写0
	// 			dequeue_head_infor_wr_en   <= 1'b1;
	// 			dequeue_head_infor_wr_addr <= dequeue_number_reg_dl;
	// 			dequeue_head_infor_wr_data <= 32'd0;
	// 			dequeue_infor_update_dl    <= 1'b0;
	// 		end
	// 	end
	// 	else begin  //有下一帧，更新为当前队首
	// 		dequeue_head_infor_wr_en   <= 1'b1;
	// 		dequeue_head_infor_wr_addr <= dequeue_number_reg_dl;
	// 		dequeue_head_infor_wr_data <= linked_list_rdata[31:0];
	// 		dequeue_infor_update_dl    <= 1'b0;
	// 	end
	// end
	else if (n_state == READ_QUEUE_INFOR) begin  //为了提速，尽快知道队首BD
		dequeue_head_infor_wr_en   <= 1'b0;
		dequeue_head_infor_wr_addr <= dequeue_number;
		dequeue_head_infor_wr_data <= 32'd0;
		// if(last_step_of_last_BD) begin
		// 	dequeue_infor_update_dl <= 1'b1;
		// end 
		// else begin
		// 	dequeue_infor_update_dl <= 1'b0;
		// end
	end
	else begin
		dequeue_head_infor_wr_en   <= 1'b0;
		dequeue_head_infor_wr_addr <= dequeue_head_infor_wr_addr;
		dequeue_head_infor_wr_data <= 32'd0;
		// dequeue_infor_update_dl    <= 1'b0;  
	end
end

// always @(posedge clk or negedge rst_n) begin
// 	if (~rst_n) begin
// 		dequeue_head_infor_wr_en   <= 1'b0;
// 		dequeue_head_infor_wr_addr <= 6'd0;
// 		dequeue_head_infor_wr_data <= 32'd0;
// 	end
// 	else if ((c_state == IDLE) && (n_state != IDLE)) begin
// 		dequeue_head_infor_wr_en   <= 1'b0;
// 		dequeue_head_infor_wr_addr <= dequeue_number_c;
// 		dequeue_head_infor_wr_data <= 32'd0;
// 	end
// 	else if (n_state == WR_DEQUEUE_RESULT) begin  //为了提速，尽快知道队首BD
// 		dequeue_head_infor_wr_en   <= 1'b0;
// 		dequeue_head_infor_wr_addr <= dequeue_number;
// 		dequeue_head_infor_wr_data <= 32'd0;
// 	end
// 	else if ((wr_dequeue_working) && (wr_result_step == 3'd3) && (linked_list_rdata[10:0] == 11'd0) && linked_list_rdata[39]) begin  //下一帧长为0，队列只有一帧
// 		if (((enqueue_number == dequeue_number_reg) && (queue_head_update_done)) || (queue_head_update_ever)) begin  //入队出队更新同一队列，入队更新队首完毕
// 			dequeue_head_infor_wr_en   <= 1'b0;
// 			dequeue_head_infor_wr_addr <= dequeue_head_infor_wr_addr;
// 			dequeue_head_infor_wr_data <= linked_list_rdata[31:0];
// 		end
// 		else begin  //入队出队没有更新同一队列，队首出完，写0
// 			dequeue_head_infor_wr_en   <= 1'b1;
// 			dequeue_head_infor_wr_addr <= dequeue_number_reg;
// 			dequeue_head_infor_wr_data <= 32'd0;
// 		end
// 	end
// 	else if ((wr_dequeue_working) && (wr_result_step == 3'd3) && linked_list_rdata[39]) begin  //有下一帧，更新为当前队首
// 		dequeue_head_infor_wr_en   <= 1'b1;
// 		dequeue_head_infor_wr_addr <= dequeue_number_reg;
// 		dequeue_head_infor_wr_data <= linked_list_rdata[31:0];
// 	end
// 	else begin
// 		dequeue_head_infor_wr_en   <= 1'b0;
// 		dequeue_head_infor_wr_addr <= dequeue_head_infor_wr_addr;
// 		dequeue_head_infor_wr_data <= 32'd0;
// 	end
// end

//队尾
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_tail_infor_wr_en   <= 1'b0;
		dequeue_tail_infor_wr_addr <= 6'd0;
		dequeue_tail_infor_wr_data <= 16'd0;
	end

	else if (linked_list_rdata[39] && (wr_result_step == 3'd3) && (linked_list_rdata[10:0] == 11'd0)) begin  //队列只有一帧
		if (((enqueue_number == dequeue_number_reg) && (queue_head_update_done)) || (queue_head_update_ever)) begin  //入队出队更新同一队列，入队更新队首完毕
			dequeue_tail_infor_wr_en   <= 1'b0;
			dequeue_tail_infor_wr_addr <= dequeue_tail_infor_wr_addr;
			dequeue_tail_infor_wr_data <= 16'd0;
		end
		else begin  //入队出队没有更新同一队列，队尾出完，写0
			dequeue_tail_infor_wr_en   <= 1'b1;
			dequeue_tail_infor_wr_addr <= dequeue_number_reg;
			dequeue_tail_infor_wr_data <= 16'd0;
		end
	end	
	// else if (dequeue_infor_update_dl) begin  //队列只有一帧
	// 	if (((enqueue_number_dl == dequeue_number_reg_dl) && (queue_head_update_done)) || (queue_head_update_ever)) begin  //入队出队更新同一队列，入队更新队首完毕
	// 		dequeue_tail_infor_wr_en   <= 1'b0;
	// 		dequeue_tail_infor_wr_addr <= dequeue_number_reg;
	// 		dequeue_tail_infor_wr_data <= 16'd0;
	// 	end
	// 	else begin  //入队出队没有更新同一队列，队尾出完，写0
	// 		dequeue_tail_infor_wr_en   <= 1'b1;
	// 		dequeue_tail_infor_wr_addr <= dequeue_number_reg_dl;
	// 		dequeue_tail_infor_wr_data <= 16'd0;
	// 	end
	// end
	else if (n_state == READ_QUEUE_INFOR) begin
		dequeue_tail_infor_wr_en   <= 1'b0;
		dequeue_tail_infor_wr_addr <= dequeue_number;
		dequeue_tail_infor_wr_data <= 16'd0;
	end
	else begin
		dequeue_tail_infor_wr_en   <= 1'b0;
		dequeue_tail_infor_wr_addr <= dequeue_tail_infor_wr_addr;
		dequeue_tail_infor_wr_data <= 16'd0;
	end
end
	//队长
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_length_infor_wr_en   <= 1'b0;
		dequeue_length_infor_wr_addr <= 6'd0;
		dequeue_length_infor_wr_data <= 16'd0;
	end
	else if (n_state == READ_QUEUE_INFOR) begin
		dequeue_length_infor_wr_en   <= 1'b0;
		dequeue_length_infor_wr_addr <= dequeue_number;
		dequeue_length_infor_wr_data <= 16'd0;
	end
	else if (c_state == WR_DEQUEUE_RESULT) begin
		dequeue_length_infor_wr_en   <= 1'b1;
		dequeue_length_infor_wr_addr <= dequeue_number_reg;
		dequeue_length_infor_wr_data <= length_infor_rd_data - dequeue_BD_num;
	end
	else begin
		dequeue_length_infor_wr_en   <= 1'b0;
		dequeue_length_infor_wr_addr <= dequeue_length_infor_wr_addr;
		dequeue_length_infor_wr_data <= 16'd0;
	end
end
	//节点长
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_node_length_wr_en   <= 1'b0;
		dequeue_node_length_wr_addr <= 3'd0;
		dequeue_node_length_wr_data <= 16'd0;
	end
	else if (n_state == READ_QUEUE_INFOR) begin
		dequeue_node_length_wr_en   <= 1'b0;
		dequeue_node_length_wr_addr <= dequeue_NodeID;
		dequeue_node_length_wr_data <= 16'd0;
	end
	else if (c_state == WR_DEQUEUE_RESULT) begin
		dequeue_node_length_wr_en   <= 1'b1;
		dequeue_node_length_wr_addr <= dequeue_NodeID_reg;
		dequeue_node_length_wr_data <= node_length_rd_data - dequeue_BD_num;
	end
	else begin
		dequeue_node_length_wr_en   <= 1'b0;
		dequeue_node_length_wr_addr <= dequeue_node_length_wr_addr;
		dequeue_node_length_wr_data <= 16'd0;
	end
end


//2021 2 10	
//更新共享缓存区已使用BD数量
	//1--查询门限
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		query_CPU_node_min_threshold <= 3'd0;
	end
	else if (n_state == READ_QUEUE_INFOR) begin
		query_CPU_node_min_threshold <= dequeue_NodeID;
	end
	else if (c_state == WR_DEQUEUE_RESULT) begin
		query_CPU_node_min_threshold <= 3'd0;
	end
	else begin
		query_CPU_node_min_threshold <= query_CPU_node_min_threshold;
	end
end
	//2--更新
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_BD_public_used_update_en  <= 1'b0;
		dequeue_BD_public_used_update_num <= 32'd0;
	end
	else if (c_state == WR_DEQUEUE_RESULT) begin
		if ((node_length_rd_data - {12'd0,dequeue_BD_num}) > CPU_node_min_threshold_data[15:0]) begin  //节点长度 - 出队帧BD数 > 最小门限，出队BD全是共享缓存区
			dequeue_BD_public_used_update_en  <= 1'b1;
			dequeue_BD_public_used_update_num <= {28'd0,dequeue_BD_num};
		end
		else if (node_length_rd_data > CPU_node_min_threshold_data[15:0]) begin  //节点长度 - 出队帧BD数 <= 最小门限，但是节点长度 > 最小门限，出队BD部分共享缓存区
			dequeue_BD_public_used_update_en  <= 1'b1;
			dequeue_BD_public_used_update_num <= {1'b0, node_length_rd_data} - {1'b0, CPU_node_min_threshold_data[15:0]} ;
		end
		else begin  //出队帧BD全部在保障区
			dequeue_BD_public_used_update_en  <= 1'b0;
			dequeue_BD_public_used_update_num <= 32'd0;
		end
	end
	else begin
		dequeue_BD_public_used_update_en  <= 1'b0;
		dequeue_BD_public_used_update_num <= 32'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		mid_valid <= 1'b0;
	end
	else if ((wr_dequeue_working) && (wr_result_step == 3'd3)) begin
		mid_valid <= (~linked_list_rdata[39]);
	end
	else begin
		mid_valid <= mid_valid;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_BD_addr <= 13'd0;
	end
	else if (wr_result_step == 3'd1) begin
		sr_BD_addr <= {1'b0,dequeue_Linked_list_ram_raddr};
	end
	else begin
		sr_BD_addr <= sr_BD_addr;
	end
end

//拉高tx_fifo读使能，准备接收下一帧
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		tx_fifo_rden_mul <= 1'b0;
		tx_fifo_rden_7   <= 1'b0;
		tx_fifo_rden_6   <= 1'b0;
		tx_fifo_rden_5   <= 1'b0;
		tx_fifo_rden_4   <= 1'b0;
		tx_fifo_rden_3   <= 1'b0;
		tx_fifo_rden_2   <= 1'b0;
		tx_fifo_rden_1   <= 1'b0;
		tx_fifo_rden_0   <= 1'b0;
	end
	else begin
	case (n_state)
		READ_TX_MUL:
		begin
			tx_fifo_rden_mul <= 1'b1;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_7:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b1;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_6:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b1;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_5:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b1;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_4:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b1;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_3:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b1;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_2:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b1;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_1:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b1;
			tx_fifo_rden_0   <= 1'b0;
		end
		READ_TXFIFO_0:
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b1;
		end
		default : /* default */
		begin
			tx_fifo_rden_mul <= 1'b0;
			tx_fifo_rden_7   <= 1'b0;
			tx_fifo_rden_6   <= 1'b0;
			tx_fifo_rden_5   <= 1'b0;
			tx_fifo_rden_4   <= 1'b0;
			tx_fifo_rden_3   <= 1'b0;
			tx_fifo_rden_2   <= 1'b0;
			tx_fifo_rden_1   <= 1'b0;
			tx_fifo_rden_0   <= 1'b0;
		end
	endcase
	end
end

//写发送调度结果FIFO
//sr_tx_fifo
// _ _ _ 5 _ _  _ _ _ _4 _ _ _ _ _ _ _ _6_ _ _ _  _ _ _ _13 _ _ _ _ _ _11 _ _ _ _ _ _ 7 _ _ _ _ _ _ 1 _ _ _ _ _ 1 _ _
//|    47~43   |     42~39    |       38~33      |     32~20    |    19~ 9     |     8~2      |     1     |     0    |
//|___reserve__|_outport_list_|__dequeue_number__|__BD_address__|_frame_length_|_valid_length_|__first_BD_|__last_BD_|
	//多播
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_mul  <= 1'b0;
		sr_tx_fifo_wdata_mul <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (mul_flag_reg == 1'b1)) begin  //1BD帧
		sr_tx_fifo_wren_mul <= 1'b1;  
		sr_tx_fifo_wdata_mul <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (mul_flag_reg == 1'b1)) begin  //一帧的首BD
		sr_tx_fifo_wren_mul  <= 1'b1;
		sr_tx_fifo_wdata_mul <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (mul_flag_reg == 1'b1)) begin  //一帧的尾BD
		sr_tx_fifo_wren_mul  <= 1'b1;
		sr_tx_fifo_wdata_mul <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (mul_flag_reg == 1'b1)) begin  //一帧的中间BD
		sr_tx_fifo_wren_mul  <= 1'b1;
		sr_tx_fifo_wdata_mul <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_mul  <= 1'b0;
		sr_tx_fifo_wdata_mul <= 48'd0;
	end
end

	//单播
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_7  <= 1'b0;
		sr_tx_fifo_wdata_7 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b111) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_7 <= 1'b1;  
		sr_tx_fifo_wdata_7 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b111) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_7  <= 1'b1;
		sr_tx_fifo_wdata_7 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b111) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_7  <= 1'b1;
		sr_tx_fifo_wdata_7 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b111) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_7  <= 1'b1;
		sr_tx_fifo_wdata_7 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_7  <= 1'b0;
		sr_tx_fifo_wdata_7 <= 48'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_6  <= 1'b0;
		sr_tx_fifo_wdata_6 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b110) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_6 <= 1'b1;  
		sr_tx_fifo_wdata_6 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b110) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_6  <= 1'b1;
		sr_tx_fifo_wdata_6 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b110) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_6  <= 1'b1;
		sr_tx_fifo_wdata_6 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b110) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_6  <= 1'b1;
		sr_tx_fifo_wdata_6 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_6  <= 1'b0;
		sr_tx_fifo_wdata_6 <= 48'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_5  <= 1'b0;
		sr_tx_fifo_wdata_5 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b101) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_5 <= 1'b1;  
		sr_tx_fifo_wdata_5 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b101) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_5  <= 1'b1;
		sr_tx_fifo_wdata_5 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b101) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_5  <= 1'b1;
		sr_tx_fifo_wdata_5 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b101) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_5  <= 1'b1;
		sr_tx_fifo_wdata_5 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_5  <= 1'b0;
		sr_tx_fifo_wdata_5 <= 48'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_4  <= 1'b0;
		sr_tx_fifo_wdata_4 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b100) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_4 <= 1'b1;  
		sr_tx_fifo_wdata_4 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b100) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_4  <= 1'b1;
		sr_tx_fifo_wdata_4 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b100) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_4  <= 1'b1;
		sr_tx_fifo_wdata_4 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b100) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_4  <= 1'b1;
		sr_tx_fifo_wdata_4 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_4  <= 1'b0;
		sr_tx_fifo_wdata_4 <= 48'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_3  <= 1'b0;
		sr_tx_fifo_wdata_3 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b011) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_3 <= 1'b1;  
		sr_tx_fifo_wdata_3 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b011) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_3  <= 1'b1;
		sr_tx_fifo_wdata_3 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b011) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_3  <= 1'b1;
		sr_tx_fifo_wdata_3 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b011) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_3  <= 1'b1;
		sr_tx_fifo_wdata_3 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_3  <= 1'b0;
		sr_tx_fifo_wdata_3 <= 48'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_2  <= 1'b0;
		sr_tx_fifo_wdata_2 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b010) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_2 <= 1'b1;  
		sr_tx_fifo_wdata_2 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b010) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_2  <= 1'b1;
		sr_tx_fifo_wdata_2 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b010) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_2  <= 1'b1;
		sr_tx_fifo_wdata_2 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b010) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_2  <= 1'b1;
		sr_tx_fifo_wdata_2 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_2  <= 1'b0;
		sr_tx_fifo_wdata_2 <= 48'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_1  <= 1'b0;
		sr_tx_fifo_wdata_1 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b001) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_1 <= 1'b1;  
		sr_tx_fifo_wdata_1 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b001) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_1  <= 1'b1;
		sr_tx_fifo_wdata_1 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b001) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_1  <= 1'b1;
		sr_tx_fifo_wdata_1 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b001) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_1  <= 1'b1;
		sr_tx_fifo_wdata_1 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_1  <= 1'b0;
		sr_tx_fifo_wdata_1 <= 48'd0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		sr_tx_fifo_wren_0  <= 1'b0;
		sr_tx_fifo_wdata_0 <= 48'd0;
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[40] && linked_list_rdata[39] && (dequeue_pri_reg == 3'b000) && (mul_flag_reg == 1'b0)) begin  //1BD帧
		sr_tx_fifo_wren_0 <= 1'b1;  
		sr_tx_fifo_wdata_0 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b1,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (linked_list_rdata[40]) && (mid_valid == 1'b0) && (dequeue_pri_reg == 3'b000) && (mul_flag_reg == 1'b0)) begin  //一帧的首BD
		sr_tx_fifo_wren_0  <= 1'b1;
		sr_tx_fifo_wdata_0 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								head_BD_addr,
								frame_length,
								7'd127,
								1'b1,
								1'b0
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && linked_list_rdata[39] && (dequeue_pri_reg == 3'b000) && (mul_flag_reg == 1'b0)) begin  //一帧的尾BD
		sr_tx_fifo_wren_0  <= 1'b1;
		sr_tx_fifo_wdata_0 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								linked_list_rdata[38:32],
								1'b0,
								1'b1
								};
	end
	else if (wr_dequeue_working && (wr_result_step == 3'd3) && (mid_valid == 1'b1) && (dequeue_pri_reg == 3'b000) && (mul_flag_reg == 1'b0)) begin  //一帧的中间BD
		sr_tx_fifo_wren_0  <= 1'b1;
		sr_tx_fifo_wdata_0 <= { 5'd0,
								outport_list_reg,
								dequeue_number_reg,
								sr_BD_addr,
								frame_length,
								7'd127,
								1'b0,
								1'b0
								};
	end
	else begin
		sr_tx_fifo_wren_0  <= 1'b0;
		sr_tx_fifo_wdata_0 <= 48'd0;
	end
end

//cpu_dequeue_cnt
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		ro_reg_np_dequeue_num <= 32'd0;
	end
	else if (c_state == WR_DEQUEUE_RESULT) begin
		ro_reg_np_dequeue_num <= ro_reg_np_dequeue_num + 32'b1;
	end
	else begin
		ro_reg_np_dequeue_num <= ro_reg_np_dequeue_num;
	end
end
// max_dequeue_length_cnt
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		time_1ms_cnt <= `ONE_MS;
	end
	else if (|time_1ms_cnt) begin
		time_1ms_cnt <= time_1ms_cnt - 20'b1;
	end
	else begin
		time_1ms_cnt <= `ONE_MS;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		frame_length_cnt <= 32'b0;
	end
	else if (~(|time_1ms_cnt) && (c_state == WR_DEQUEUE_RESULT)) begin
		frame_length_cnt <= {18'b0,frame_length + 11'd24,3'b0};
	end
	else if(~(|time_1ms_cnt)) begin
		frame_length_cnt <= 32'b0;
	end
	else if (c_state == WR_DEQUEUE_RESULT) begin
		frame_length_cnt <= frame_length_cnt + {18'b0,frame_length + 11'd24,3'b0};
	end
	else begin
		frame_length_cnt <= frame_length_cnt;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		ro_reg_np_max_tx_length <= 32'b0;
	end
	else if (~(|time_1ms_cnt)) begin
		ro_reg_np_max_tx_length <= /*((frame_length_cnt > ro_reg_np_max_tx_length)?*/ frame_length_cnt /*: ro_reg_np_max_tx_length)*/;
	end
	else begin
		ro_reg_np_max_tx_length <= ro_reg_np_max_tx_length;
	end
end

//count tx frame for cpu
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		tx_frame_cnt_node_0  <= 32'b0;
	end
	else if ((c_state == WR_DEQUEUE_RESULT) && dequeue_NodeID_reg == 3'd0) begin
		tx_frame_cnt_node_0  <= tx_frame_cnt_node_0 + 32'b1;
	end
	else begin
		tx_frame_cnt_node_0  <= tx_frame_cnt_node_0;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		tx_frame_cnt_node_1  <= 32'b0;
	end
	else if ((c_state == WR_DEQUEUE_RESULT) && dequeue_NodeID_reg == 3'd1) begin
		tx_frame_cnt_node_1  <= tx_frame_cnt_node_1 + 32'b1;
	end
	else begin
		tx_frame_cnt_node_1  <= tx_frame_cnt_node_1;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		tx_frame_cnt_node_2  <= 32'b0;
	end
	else if ((c_state == WR_DEQUEUE_RESULT) && dequeue_NodeID_reg == 3'd2) begin
		tx_frame_cnt_node_2  <= tx_frame_cnt_node_2 + 32'b1;
	end
	else begin
		tx_frame_cnt_node_2  <= tx_frame_cnt_node_2;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		tx_frame_cnt_node_3  <= 32'b0;
	end
	else if ((c_state == WR_DEQUEUE_RESULT) && dequeue_NodeID_reg == 3'd3) begin
		tx_frame_cnt_node_3  <= tx_frame_cnt_node_3 + 32'b1;
	end
	else begin
		tx_frame_cnt_node_3  <= tx_frame_cnt_node_3;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		tx_frame_cnt_node_4  <= 32'b0;
	end
	else if ((c_state == WR_DEQUEUE_RESULT) && dequeue_NodeID_reg == 3'd4) begin
		tx_frame_cnt_node_4  <= tx_frame_cnt_node_4 + 32'b1;
	end
	else begin
		tx_frame_cnt_node_4  <= tx_frame_cnt_node_4;
	end
end


//mark debug
(*mark_debug = "true"*) reg [31:0] dequeue_cnt_mul,dequeue_cnt_7,dequeue_cnt_6,dequeue_cnt_5,dequeue_cnt_4,dequeue_cnt_3,dequeue_cnt_2,dequeue_cnt_1,dequeue_cnt_0;
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_mul <= 32'd0;
	end
	else if (sr_tx_fifo_wren_mul && sr_tx_fifo_wdata_mul[0] == 1'b1) begin
		dequeue_cnt_mul <= dequeue_cnt_mul + 1'b1;
	end
	else begin
		dequeue_cnt_mul <= dequeue_cnt_mul;
	end
end

always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_7 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_7 && sr_tx_fifo_wdata_7[0] == 1'b1) begin
		dequeue_cnt_7 <= dequeue_cnt_7 + 1'b1;
	end
	else begin
		dequeue_cnt_7 <= dequeue_cnt_7;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_6 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_6 && sr_tx_fifo_wdata_6[0] == 1'b1) begin
		dequeue_cnt_6 <= dequeue_cnt_6 + 1'b1;
	end
	else begin
		dequeue_cnt_6 <= dequeue_cnt_6;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_5 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_5 && sr_tx_fifo_wdata_5[0] == 1'b1) begin
		dequeue_cnt_5 <= dequeue_cnt_5 + 1'b1;
	end
	else begin
		dequeue_cnt_5 <= dequeue_cnt_5;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_4 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_4 && sr_tx_fifo_wdata_4[0] == 1'b1) begin
		dequeue_cnt_4 <= dequeue_cnt_4 + 1'b1;
	end
	else begin
		dequeue_cnt_4 <= dequeue_cnt_4;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_3 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_3 && sr_tx_fifo_wdata_3[0] == 1'b1) begin
		dequeue_cnt_3 <= dequeue_cnt_3 + 1'b1;
	end
	else begin
		dequeue_cnt_3 <= dequeue_cnt_3;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_2 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_2 && sr_tx_fifo_wdata_2[0] == 1'b1) begin
		dequeue_cnt_2 <= dequeue_cnt_2 + 1'b1;
	end
	else begin
		dequeue_cnt_2 <= dequeue_cnt_2;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_1 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_1 && sr_tx_fifo_wdata_1[0] == 1'b1) begin
		dequeue_cnt_1 <= dequeue_cnt_1 + 1'b1;
	end
	else begin
		dequeue_cnt_1 <= dequeue_cnt_1;
	end
end
always @(posedge clk or negedge rst_n) begin
	if (~rst_n) begin
		dequeue_cnt_0 <= 32'd0;
	end
	else if (sr_tx_fifo_wren_0 && sr_tx_fifo_wdata_0[0] == 1'b1) begin
		dequeue_cnt_0 <= dequeue_cnt_0 + 1'b1;
	end
	else begin
		dequeue_cnt_0 <= dequeue_cnt_0;
	end
end


`ifdef SIM
//****************************打印队列信息************************************//
integer dequeue_BD_mul;
integer dequeue_BD_7;
integer dequeue_BD_6;
integer dequeue_BD_5;
integer dequeue_BD_4;
integer dequeue_BD_3;
integer dequeue_BD_2;
integer dequeue_BD_1;
integer dequeue_BD_0;
initial
begin
	dequeue_BD_mul = $fopen("dequeue_BD_mul.txt");
	dequeue_BD_7   = $fopen("dequeue_BD_7.txt");
	dequeue_BD_6   = $fopen("dequeue_BD_6.txt");
	dequeue_BD_5   = $fopen("dequeue_BD_5.txt");
	dequeue_BD_4   = $fopen("dequeue_BD_4.txt");
	dequeue_BD_3   = $fopen("dequeue_BD_3.txt");
	dequeue_BD_2   = $fopen("dequeue_BD_2.txt");
	dequeue_BD_1   = $fopen("dequeue_BD_1.txt");
	dequeue_BD_0   = $fopen("dequeue_BD_0.txt");
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_mul) begin
		$fwrite(dequeue_BD_mul,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_mul[1],sr_tx_fifo_wdata_mul[31:19],sr_tx_fifo_wdata_mul[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_7) begin
		$fwrite(dequeue_BD_7,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_7[1],sr_tx_fifo_wdata_7[31:19],sr_tx_fifo_wdata_7[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_6) begin
		$fwrite(dequeue_BD_6,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_6[1],sr_tx_fifo_wdata_6[31:19],sr_tx_fifo_wdata_6[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_5) begin
		$fwrite(dequeue_BD_5,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_5[1],sr_tx_fifo_wdata_5[31:19],sr_tx_fifo_wdata_5[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_4) begin
		$fwrite(dequeue_BD_4,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_4[1],sr_tx_fifo_wdata_4[31:19],sr_tx_fifo_wdata_4[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_3) begin
		$fwrite(dequeue_BD_3,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_3[1],sr_tx_fifo_wdata_3[31:19],sr_tx_fifo_wdata_3[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_2) begin
		$fwrite(dequeue_BD_2,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_2[1],sr_tx_fifo_wdata_2[31:19],sr_tx_fifo_wdata_2[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_1) begin
		$fwrite(dequeue_BD_1,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_1[1],sr_tx_fifo_wdata_1[31:19],sr_tx_fifo_wdata_1[0]);
	end
end

always @(posedge clk) begin
	if (sr_tx_fifo_wren_0) begin
		$fwrite(dequeue_BD_0,"FIRST_FLAG:%d--BD:%d--LAST_FLAG:%d\n",sr_tx_fifo_wdata_0[1],sr_tx_fifo_wdata_0[31:19],sr_tx_fifo_wdata_0[0]);
	end
end

initial
begin
	wait(dequeue_cnt_mul == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_mul);
end

initial
begin
	wait(dequeue_cnt_7 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_7);
end

initial
begin
	wait(dequeue_cnt_6 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_6);
end

initial
begin
	wait(dequeue_cnt_5 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_5);
end

initial
begin
	wait(dequeue_cnt_4 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_4);
end

initial
begin
	wait(dequeue_cnt_3 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_3);
end

initial
begin
	wait(dequeue_cnt_2 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_2);
end

initial
begin
	wait(dequeue_cnt_1 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_1);
end

initial
begin
	wait(dequeue_cnt_0 == `SEND_NUM && c_state == IDLE)
		$fclose(dequeue_BD_0);
end

`endif

endmodule
